package com.sen.common.utils;

import java.math.BigDecimal;

/**
 * 数字型工具类.
 * 
 * @author sen
 */
public final class NumberUtils {

	private NumberUtils() {
		// empty
	}

	/**
	 * 是否大于0?
	 * 
	 * @param value
	 *            要检测的值
	 * @return 返回true, 若被检测的值大于0, 否则返回false(当值为null或小于0时)
	 */
	public static boolean greaterThanZero(int value) {
		return greaterThan(Long.valueOf(value), 0L);
	}

	/**
	 * 是否大于0?
	 * 
	 * @param value
	 *            要检测的值
	 * @return 返回true, 若被检测的值大于0, 否则返回false(当值为null或小于0时)
	 */
	public static boolean greaterThanZero(Long value) {
		return greaterThan(value, 0L);
	}

	/**
	 * 是否大于1?
	 * 
	 * @param value
	 *            要检测的值
	 * @return 返回true, 若被检测的值大于1, 否则返回false(当值为null或小于1时)
	 */
	public static boolean greaterThanOne(Long value) {
		return greaterThan(value, 1L);
	}

	/**
	 * 是否大于指定的值?
	 * 
	 * @param value
	 *            要检测的值
	 * @param compareValue
	 *            比较的值
	 * @return 返回true, 若被检测的值大于比较的值, 否则返回false(当值为null或小于比较的值时)
	 */
	public static boolean greaterThan(Long value, Long compareValue) {
		if (null == value) {
			return false;
		}
		if (null == compareValue) {
			return true;
		}
		return value.longValue() > compareValue.longValue();
	}

	/**
	 * 返回精确度到小数点后两位的BigDecimal.
	 * 
	 * @param value
	 *            要进行精确度的数值.
	 * @return 返回精确度到小数点后两位的BigDecimal.
	 */
	public static BigDecimal precision(double value) {
		return precision(value, 2);
	}

	public static BigDecimal precision(Double value) {
		return precision(value, 2);
	}

	/**
	 * 返回指定精确度的BigDecimal.
	 * 
	 * @param value
	 *            要进行精确度的数值.
	 * @param precision
	 *            精确度
	 * @return 指定精确度的BigDecimal
	 */
	public static BigDecimal precision(double value, int precision) {
		BigDecimal bd = new BigDecimal(value);
		return bd.setScale(precision, BigDecimal.ROUND_HALF_UP);
	}

	public static BigDecimal precision(Double value, int precision) {
		return precision(value == null ? 0l : value.doubleValue(), precision);
	}

	/**
	 * 求和并按四舍五入返回recision要求的位数精度
	 * 
	 * @param a1
	 * @param a2
	 * @param precision
	 *            返回的精度
	 * @return a1 + a2
	 */
	public static double doubleAddPrecision(double a1, double a2, int precision) {
		BigDecimal b1 = new BigDecimal(Double.toString(a1));
		BigDecimal b2 = new BigDecimal(Double.toString(a2));

		return (b1.add(b2)).setScale(precision, BigDecimal.ROUND_HALF_UP).doubleValue();
	}

	/**
	 * 求差并按四舍五入返回recision要求的位数精度
	 * 
	 * @param a1
	 * @param a2
	 * @param precision
	 *            返回的精度
	 * @return a1 - a2
	 */
	public static double doubleSubPrecision(double a1, double a2, int precision) {
		BigDecimal b1 = new BigDecimal(Double.toString(a1));
		BigDecimal b2 = new BigDecimal(Double.toString(a2));

		return (b1.subtract(b2)).setScale(precision, BigDecimal.ROUND_HALF_UP).doubleValue();
	}

	/**
	 * 求乘并按四舍五入返回recision要求的位数精度
	 * 
	 * @param a1
	 * @param a2
	 * @param precision
	 *            返回的精度
	 * @return a1 * a2
	 */
	public static double doubleMulPrecision(double a1, double a2, int precision) {
		BigDecimal b1 = new BigDecimal(Double.toString(a1));
		BigDecimal b2 = new BigDecimal(Double.toString(a2));

		return (b1.multiply(b2)).setScale(precision, BigDecimal.ROUND_HALF_UP).doubleValue();
	}

	/**
	 * 求商并按四舍五入返回recision要求的位数精度
	 * 
	 * @param a1
	 * @param a2
	 * @param precision
	 *            返回的精度
	 * @return a1 / a2
	 */
	public static double doubleDivPrecision(double a1, double a2, int precision) {
		BigDecimal b1 = new BigDecimal(Double.toString(a1));
		BigDecimal b2 = new BigDecimal(Double.toString(a2));

		return b1.divide(b2, precision, BigDecimal.ROUND_HALF_UP).doubleValue();
	}

	public static double doubleAdd(double a1, double a2) {
		return doubleAddPrecision(a1, a2, 2);
	}

	public static double doubleSub(double a1, double a2) {
		return doubleSubPrecision(a1, a2, 2);
	}

	public static double doubleMul(double a1, double a2) {
		return doubleMulPrecision(a1, a2, 2);
	}

	public static double doubleDiv(double a1, double a2) {
		return doubleDivPrecision(a1, a2, 2);
	}
}
